package bbalgae_JavaJDBC;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class J02_Departments {
/**
   	1.JDBC 드라이버 불러오기
	JDBC 드라이버는 데이터베이스에 연결 해야 할 필요가 있는 자바 클래스와JDBC드라이버 사이 계약을 정의하는 인터페이스들을 구현한 것
	드라이버는 jar파일 형태로 배포
	
	JDBC 드라이버를 불러오는 방법에는 
	수동 manual과 동적 dynamic이 있음
	Class.forName("oracle.jdbc.driver.OracleDriver")
	Class.forName(DRV);
	forName 메서드는 ClassNotFoundException 예외를 던지기 때문에 try-catch 블럭안에 둬야한다.
	
	2.데이터베이스 연결하기
	Connection 인터페이스는 데이터베이스 연결객체를 위한 그릇(템플릿)임
	연결객체를 얻으려면 DriverManager 클래스의 getConnection 메소드를 이용
	getConnection 메소드는 앞의 과정에서 메모리에 올려둔 드라이버를 찾고 URL, USR, PWD를 통해 데이터베이스 서버에
	연결 하고 그 결과를 Connection으로 반환
	
	JDBC 연결시 사용하는 URL 형식은 다음과 같음
	jdbc:프로토콜:하위이름
	jdbc:oracle:thin:@주소:포트:DB이름?user=아이디&amp;password=비밀번호(&amp; 대신 &로 써도됨 &amp를 주로 사용)
	jdbc:mysqal://주소/DB이름?user=아이디&password=비밀번호
	
	3.SQL 질의문 생성 및 실행
	Statement, PreparedStatement객체는 실행할 SQL 질의문을 의미함 
	createStatement, PreparedStatement 메소드를 이용해서 위 객체를 얻을 수 있다.
	단, 위 메소드를 호출하때에는 생성할 SQL 질의문을 인자로 전달해야 함. 
	생성한 객체를 실행하려면 executeQuery나 excuteUpdate 메소드를 이용함
	executeQuery : SQL 질의문이 select인 경우
	executeUpdate : insert, update, delete,create, alter, drop 인경우
	
	executeUpdate의 실행결과는 질의문에 의해 변경/삭제된 레코드 수나 0을 반환
	
	executeQuery의 실행결과는 질의문에 의해 생성된 데이터를 담아두는 ResultSet 객체를 반환
	단 생성된 데이터가 없는 경우 null은 아님
	
	Statement에서 파생된 PreparedStatement는 Statement의 인기있는 대체제임.
	SQL문을 미리 컴파일하고 저장해두기 때문에 추후 동일한 SQL문을 실행할 경우 빠르게 처리 할 수 있는 장점이 제공된다.
	
	4.결과집합 ResultSet 객체다루기
	결과 집합은 Statemenent, PreparedStatement에서 반환된 데이터 베이스 테이블을 의미함
	결과 집합 객체는 현재 데이터 행을 가리키는 커서를 가지고 있음
	커서는 처음에는 테이블을 가리키고 있다가 next메소드가 호출되면 첫번째 레코드로 이동하고 true 또는 false를 반환함
	true가 반환되면 현재 레코드가 존재한다는 의미 false가 반환되면 더이상 레코드가 없다는 의미
	while을 이용해서 모든 레코드에 접근할 수 있음
	
	next메소드로 레코드에 접근한 뒤, 각필드 값을 가져오려면 getXxx메소드를 사용해야한다.
	일반적으로 필드 값을 문자열로 가져오는 getString 메소드를 많이 사용
	필드값을 int로 가져오려면 getInt를 사용하면됨
	
	getXxx메도에 필드이름 또는 필드위치 값을 인자로 전달해서 필드값을 가져올 수 있음.
	getString(1)
	getString("department_id")
	
	5.JDBC 객체닫기
	모든 JDBC객체는 사용한 후 그 들의 close 메소드를 호출해서 항상 닫아야함.
	try{
	     ....
	     rs.close(); pstmt.close(); conn.close();
	     }catch(Exception ex){
	     ex.printStackTrace();
	     }
	    위 코드는 완벽하지않음.
	    만일 pstmt.close();가 실패하는 경우 그 아래 코드는 실행되지 않기 때문임.
	    따라서, close관련 코드는 finally 절에 작성 해야함
	    즉, 예외가 발생하든 하지 않든 간에 무조건 실행되어야 하는 코드는 finally절에 작성하면 프로그램이 다소 완벽해진다.
*/
	public static void main(String[] args) {
		
		final String DRV = "oracle.jdbc.driver.OracleDriver";
		final String URL = "jdbc:oracle:thin:@112.216.253.125:1521:xe";
		final String USR = "bbalgae";
		final String PWD = "bbalgae";
		
	 Connection conn = null;
	 PreparedStatement pstmt = null;
	 ResultSet rs = null;
	 String SQL = "select * from departments";
	try{
		Class.forName(DRV);
		conn = DriverManager.getConnection(URL, USR, PWD);
		pstmt = conn.prepareStatement(SQL);
		rs = pstmt.executeQuery();
		
		if(rs.next()){
			do{
				System.out.print(rs.getString(1));
				System.out.print(" / ");
				System.out.print(rs.getString("department_name"));
				System.out.print(" / ");
				System.out.print(rs.getString("manager_id"));
				System.out.print(" / ");
				System.out.print(rs.getString(4));
				System.out.println("  ");
				
			}while(rs.next());
			
		}else{
			System.out.println("데이터없음");
			
		}
		
	}
	catch(Exception e){
		e.printStackTrace();
	} finally {
		if(rs!=null)try{rs.close(); rs=null; }catch(Exception e){};
		if(pstmt!=null)try{pstmt.close(); pstmt=null;}catch(Exception e){};
		if(conn!=null)try{conn.close(); conn=null;} catch(Exception e){};
	}
	
	}

}
